//:C07:WildLifeMonitor.cpp
#include <algorithm>
#include <bits/types/time_t.h>
#include <cstdlib>
#include <cstddef>
#include <ctime>
#include <iterator>
#include <map>
#include <iostream>
#include <ostream>
#include <sstream>
#include <vector>
using namespace std;

class DataPoint
{
    int x, y;   // Location coordinates
    time_t time;    // Time of Sighting
    public:
        DataPoint() : x(0), y(0), time(0) {}
        DataPoint(int xx, int yy, time_t tm) :
            x(xx), y(yy), time(tm) {}
        // Synthesized operator = , copy-construtor OK
        int getX() const { return x; }
        int getY() const { return y; }
        const time_t* getTime() const { return &time; }
};

string animal[] = 
{
    "chipmunk", "beaver", "marmot", "weasel",
    "squirrel", "ptarmigan", "bear", "eagle",
    "hawk", "vole", "deer", "otter", "hummingbird",
};

const int ASZ = sizeof animal / sizeof *animal;
vector<string> animals(animal, animal + ASZ);
// all the information is contained in a 
// "Sighting," which can be sent to an ostream:
typedef pair<string, DataPoint> Sighting;

ostream&
operator<<(ostream& os, const Sighting& s)
{
    return os << s.first << " sighted at x = "
       << s.second.getX() << ", y = " << s.second.getY()
       << ", time = " << ctime(s.second.getTime());
}

// A generator for Sightings:
class SightingGen
{
    vector<string>& animals;
    enum { D = 100 };
    public:
        SightingGen(vector<string>& an) : animals(an) {}
        Sighting operator()()
        {
            Sighting result;
            int select = rand() % animals.size();
            result.first = animals[select];
            result.second = DataPoint(
                rand() % D, rand() % D, time(0));
            return result;    
        }
};

// Display a menu of animals, allow the user to
// select one, return the index value:
int menu()
{
    typedef multimap<string, DataPoint> DataMap;
    typedef DataMap::iterator DMIter;
    DataMap sightings;
    srand(time(0));    // Randomize
    generate_n(inserter(sightings, sightings.begin()), 50, SightingGen(animals));
    // Print everything:
    copy(sightings.begin(), sightings.end(),
    ostream_iterator<Sighting>(cout, ""));
    // Print sightings for selected animal:
    for (int count = 1; count < 10; count++)
    {
        // Use menu to get selection:
        // int i = menu();
        // Generate randomly (for automated testing)
        int i = rand() % animals.size();
        // Iterators in "range" denote begin, one
        // past end of matching range:
        pair<DMIter, DMIter> range = 
          sightings.equal_range(animals[i]);
        copy(range.first, range.second,
            ostream_iterator<Sighting>(cout, ""));  
    }
}